package com.ihm.labyrinth;

import java.io.IOException;

import org.xmlpull.v1.XmlPullParserException;

import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import com.ihm.labyrinth.layout.BoiteDialogue;
import com.ihm.labyrinth.layout.MainActivity;
import com.ihm.labyrinth.levels.Level;
import com.ihm.labyrinth.levels.LevelManager;
import com.ihm.labyrinth.listener.GameListener;
import com.ihm.labyrinth.song.PlaySong;

public class LabMainActivity extends Activity implements SensorEventListener, GameListener, OnSharedPreferenceChangeListener {

	
	private static final int RESULT_SETTINGS = 1;
	
	private SharedPreferences prefs;
	private PlaySong playSong = null;
	
	LabyrinthePanel panel;
	
	private Vibrator vibrator;
	private  int vibratorDuration = 35;
	public float reductionCoef = 0.3f;
	
	public int targetFPS;
	
	private MainGameThread thread;
	
	private PhysicsWorld world;
	
	private SensorManager sensorManager;
	
	private LevelManager levelManager;
	
	private Bitmap bitmap;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.d("TAG", "Create...");
		super.onCreate(savedInstanceState);
		
		getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		
		//creer le son
		this.playSong = new PlaySong(this);
		
		prefs = PreferenceManager.getDefaultSharedPreferences(this);//get the preferences that are allowed to be given
		prefs.registerOnSharedPreferenceChangeListener(this);//set the listener to listen for changes in the preferences
		
		levelManager = new LevelManager(this, 0,0);
		
		initFromSettings();
		
		Level level = null;
		
		world = new PhysicsWorld(this);
		world.addGameListener(this);
		
		
		
		level = levelManager.getActualLevel();
		
		// Pas de niveau on quitte brutalement!^^
		if(level == null){
			Log.e("ERROR", "NO LEVEL TO START WITH!");
			this.finish();
		}
		bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.texture_andriod, new BitmapFactory.Options());
		if(!prefs.getBoolean(SettingsActivity.KEY_DISPLAY, false))
			world.setBitmap(bitmap);
		else
			world.setBitmap(null);
		
		world.create(level, 
				computeXResolution(level.getWidth()), 
				computeYResolution(level.getHeight()));
		
		
		
		panel = new LabyrinthePanel(this);
		
		Log.d("HELLO", "FPS : " + targetFPS);
		thread = new MainGameThread(panel.getHolder(), world, targetFPS);
		
		
		setContentView(panel);
	}
	
	@Override
	protected void onStart(){
		Log.d("TAG", "Start...");
		super.onStart();
		//prefs.registerOnSharedPreferenceChangeListener(this);
		registerAccelerometer();
		vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
		startThread();
	}
	
	private void startThread() {
		thread.setRunning(true);
		try{
			thread.start();
		}catch(IllegalThreadStateException e){
			try{
				thread = new MainGameThread(panel.getHolder(), world, targetFPS);
				thread.setRunning(true);
				thread.start();
			}catch(Exception exs){
				Log.e("THREAD_ERROR", "Exception in Exception");
			}
		}
		catch(Exception e){
			Log.e("THREAD_ERROR", "OHTER EXPECTION IN THRED STARTING");
		}
		
	}

	@Override
    protected void onResume() {
		Log.d("TAG", "Resume...");
        super.onResume();
    }
    @Override
    protected void onPause() {
    	Log.d("TAG", "Pause...");
    	thread.setRunning(false);
        super.onPause();
        unregisterAccelerometer();
    }
	
    @Override
	protected void onDestroy() {
		Log.d("TAG", "Destroying...");
		super.onDestroy();
		
		Log.d("TAG", "Surface is being destroyed");
		stopThread();
		
		//Commit the preference changes
		SharedPreferences.Editor prefEditor = prefs.edit();
		prefEditor.putString(SettingsActivity.KEY_MAX_LEVEL, ""+levelManager.getMaxLevel());
		prefEditor.putString(SettingsActivity.KEY_ACTUAL_LEVEL, ""+levelManager.getActualPosition());
		prefEditor.commit();
		prefs.unregisterOnSharedPreferenceChangeListener(this);
	 }

    private void stopThread() {
    	boolean retry = true;
		thread.setRunning(false);
		while (retry) {
			try {
				thread.join();
				retry = false;
			} catch (InterruptedException e) {
				// try again shutting down the thread
			}
		}
		
	}

	@Override
    protected void onStop() {
	  Log.d("TAG", "Stopping...");
	  //prefs.unregisterOnSharedPreferenceChangeListener(this);
	  super.onStop();
	 
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu){
      	MenuInflater inflater = getMenuInflater();//create a MenuInflater to help use the menu that we already made in XML
      	inflater.inflate(R.menu.settings, menu);//inflate this menu with the XML resource that was created earlier
      	return true;//to allow method to be displayed
    }
    
    //@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
	@Override
    public boolean onOptionsItemSelected(MenuItem item){
      switch(item.getItemId()){//decide which MenuItem was pressed based on its id
      case R.id.menu_settings:
	    	 Intent intent = new Intent(this, SettingsActivity.class);
	    	 Bundle extra = new Bundle();
	    	 Bundle actualPosition = new Bundle();
	    	 if(prefs.getBoolean(SettingsActivity.KEY_ADMIN, false)){
	 				levelManager.setMaxLevel(levelManager.getLevels().size()-1);
	 		 }
	    	 actualPosition.putString(SettingsActivity.KEY_ACTUAL_LEVEL, ""+levelManager.getActualPosition());
	    	 extra.putBundle(SettingsActivity.KEY_ACTUAL_LEVEL, actualPosition);
	    	 extra.putBundle(SettingsActivity.KEY_LEVELS, levelManager.getLevelBundle());
	    	 intent.putExtras(extra);
	      	 startActivity(intent);//start the PrefsActivity.java
	      	break;
      	case R.id.menu_restart:
      		restartPreferences();
      		break;
      		
      }

      return true; //to execute the event here
    }
    
	private void restartPreferences(){
		levelManager.setActualPosition(0);
		levelManager.setMaxLevel(0);
		stopThread();
			world.create(levelManager.getActualLevel(), computeXResolution(world.getLevel().getWidth()), computeYResolution(world.getLevel().getHeight()));
		startThread();
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		
		
		
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		
		world.setGravity(event.values[0]*reductionCoef, event.values[1]*reductionCoef);
		Log.d("SENSOR", "x : " + event.values[0]);
		Log.d("SENSOR", "y : " + event.values[1]);
		
	}
	
	private void initFromSettings(){
		targetFPS = Integer.parseInt(prefs.getString(SettingsActivity.KEY_FPS, "40"));
		int maxLevel = Integer.parseInt(prefs.getString(SettingsActivity.KEY_MAX_LEVEL, "0"));
		int actualLevel = Integer.parseInt(prefs.getString(SettingsActivity.KEY_ACTUAL_LEVEL, "0"));
		
		try {
			levelManager.parseLevels();
		} catch (XmlPullParserException e) {
			Log.d("LEVEL", "Parser Error");
			e.printStackTrace();
		} catch (IOException e) {
			Log.d("LEVEL", "IO Error");
			e.printStackTrace();
		}
		
		if(maxLevel >= levelManager.getLevels().size()){
			maxLevel = 0;
			actualLevel = 0;
			
		}else if(actualLevel > maxLevel)
			actualLevel = 0;
		levelManager.setActualPosition(actualLevel);
		levelManager.setMaxLevel(maxLevel);
		
	}
	
	private void registerAccelerometer(){
		sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
		// add listener. The listener will be HelloAndroid (this) class
		sensorManager.registerListener(this, 
								sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
								SensorManager.SENSOR_DELAY_GAME);
	}
	
	private void unregisterAccelerometer(){
		sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
		// add listener. The listener will be HelloAndroid (this) class
		sensorManager.unregisterListener(this);
	}
	
	private float computeXResolution(int mapX){
		return getWidth()/(float)mapX;
	}
	
	private float computeYResolution(int mapY){
		return getHeight()/(float)mapY;
	}

	@Override
	public void isDead() {
		Log.d("LISTENER", "Dead");

		
		//**********************************************************
		if(prefs.getBoolean(SettingsActivity.KEY_SON, false))
			this.playSong.playSongLost();
		//**********************************************************

		vibrate();

		world.restartLevel();
	}

	@Override
	public void won() {
		Log.d("LISTENER", "Won");

		
		//**********************************************************
		if(prefs.getBoolean(SettingsActivity.KEY_SON, false))
			this.playSong.playSongWin();
		//**********************************************************

		vibrate();

		try{
			Level level = levelManager.nextLevel();
			if(level != null){
				world.create(level, computeXResolution(level.getWidth()), computeYResolution(level.getHeight()));
			}else{
				MainActivity.finJeux = true;
				this.finish();
			}
		}catch(Exception e){
			MainActivity.finJeux = true;
			this.finish();
		}
		
	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
			String key) {
		if(key.equals(SettingsActivity.KEY_FPS)){
			thread.setFPS(Integer.parseInt(prefs.getString(key, "40")));
		}
		if(key.equals(SettingsActivity.KEY_LEVEL)){
			levelManager.setActualPosition(Integer.parseInt(prefs.getString(key, "0")));
			Level level =  levelManager.getActualLevel();
			world.create(level,computeXResolution(level.getWidth()), computeYResolution(level.getHeight()));
		}
		if(key.equals(SettingsActivity.KEY_FPS)){
			
			thread.setFPS(Integer.parseInt(prefs.getString(key, "40")));
		}
		if(key.equals(SettingsActivity.KEY_DISPLAY)){
			if(!prefs.getBoolean(key, false)){
				world.setBitmap(bitmap);
				world.create(world.getLevel(), computeXResolution(world.getLevel().getWidth()), computeYResolution(world.getLevel().getHeight()));
			}else{
				world.setBitmap(null);
				world.create(world.getLevel(), computeXResolution(world.getLevel().getWidth()), computeYResolution(world.getLevel().getHeight()));
				
			}
		}
		
		
	}
	
	private void vibrate() {
		if(prefs.getBoolean(SettingsActivity.KEY_VIBRATION, false))
			vibrator.vibrate(vibratorDuration);
	}
	
	public int getTargetFPS() {
		return targetFPS;
	}

	public int getWidth() {
		return getWindowManager().getDefaultDisplay().getWidth();
	}

	public int getHeight() {
		return getWindowManager().getDefaultDisplay().getHeight();
	}
}
